/*
    定义通讯录类型，实现添加联系人方法，以及将通讯录对象序列化结果写入到文件中
*/
#include <iostream>
#include <fstream>
#include "address_book.pb.h"

// 新增一条联系人数据
void AddContacts(addressbook::Contacts* contactsPtr)
{
    std::cout << "----------------新增联系⼈----------------" << std::endl;
    // 1. 姓名
    std::cout << "输入联系人姓名：";
    std::string name;
    getline(std::cin, name);
    contactsPtr->set_name(name);

    // 2. 年龄
    std::cout << "输入联系人年龄：";
    int age;
    std::cin >> age;
    contactsPtr->set_age(age);

    // 3. 电话
    // 将输入缓冲区的回车符去掉
    // 终止条件：要么清除256个字节，要么遇到回车符，要么缓冲区没有数据
    std::cin.ignore(256, '\n');
    std::cout << "输入联系人电话（输⼊回⻋完成电话新增）：" << std::endl;
    for(int i = 1; ; i++)
    {
        std::cout << "输入第" << i << "个电话：";
        std::string number;
        getline(std::cin, number);
        if(number.empty())
            break;
        addressbook::Contacts_Phone* phonePtr = contactsPtr->add_phones();
        phonePtr->set_number(number);

        std::cout << "输入第" << i << "个电话类型(1.移动电话 2.固定电话): ";
        int type;
        std::cin >> type;
        std::cin.ignore(256, '\n');
        switch(type)
        {
        case 1:
            phonePtr->set_type(addressbook::Contacts_Phone_Type_MP); // 如果枚举值没有被设置，protobuf会使用默认值0填充
            break;
        case 2:
            phonePtr->set_type(addressbook::Contacts_Phone_Type_TEL);
            break;
        default:
            std::cout << "非法选择，使用默认值" << std::endl;
        }
    }

    // 4. 地址
    addressbook::Address addr;
    std::cout << "输入联系人家庭地址：";
    std::string home_address;
    getline(std::cin, home_address);
    addr.set_home_address(home_address);

    std::cout << "输入联系人单位地址: ";
    std::string unit_address;
    getline(std::cin, unit_address);
    addr.set_unit_address(unit_address);
    google::protobuf::Any* addrPtr = contactsPtr->mutable_address();
    addrPtr->PackFrom(addr); // 将地址对象打包成Any对象

    // 5. 联系方式
    std::cout << "输入联系方式类型(1.QQ 2.微信): ";
    int type;
    std::cin >> type;
    std::cin.ignore(256, '\n');
    std::string contactInfo;
    if(type == 1)
    {
        std::cout << "输入QQ: ";
        getline(std::cin, contactInfo);
        contactsPtr->set_qq(contactInfo);
    }
    else if(type == 2)
    {
        std::cout << "输入微信: ";
        getline(std::cin, contactInfo);
        contactsPtr->set_wechat(contactInfo);
    }
    else
    {
        std::cout << "非法选择，默认没有联系方式" << std::endl;
    }

    // 6、备注
    std::cout << "输入备注(输入回车完成备注新增): " << std::endl;
    std::string commitTitle, commitContent;
    for(int i = 1; ; i++)
    {
        std::cout << "输入备注" << i << "标题: ";
        getline(std::cin, commitTitle);
        if(commitTitle.empty())
            break;

        std::cout << "输入备注" << i << "内容: ";
        getline(std::cin, commitContent);
        contactsPtr->mutable_commits()->insert({commitTitle, commitContent});
    }
    
    std::cout << "-------------------结束-------------------" << std::endl;
}

int main()
{
    // 1. 打开文件，如果存在从文件中加载数据
    std::fstream input("address_book.bin", std::ios::in | std::ios::binary);
    addressbook::AddressBook addressBook;
    if(input) // 文件存在
    {
        bool ret = addressBook.ParseFromIstream(&input); // 从文件流中反序列化
        input.close();
        if(ret == false)
        {
            std::cout << "从文件中反序列化通讯录失败" << std::endl;
            return -1;
        }
    }

    // 2. 新增一条联系人
    AddContacts(addressBook.add_contacts());

    // 3. 序列化到文件流中
    std::fstream output("address_book.bin", std::ios::out | std::ios::binary | std::ios::trunc);
    if(output)
    {
        bool ret = addressBook.SerializeToOstream(&output); // 序列化到文件流中
        output.close();
        if(ret == false)
        {
            std::cout << "序列化通讯录失败" << std::endl;
            return -1;
        }
        else
        {
            std::cout << "序列化通讯录成功，总共联系人：" << addressBook.contacts_size() << "个" << std::endl;
        }
    }
    else
    {
        std::cout << "打开文件失败" << std::endl;
        return -1;
    }
    return 0;
}